#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<signal.h>
#include<sys/time.h>
#include<fcntl.h>
#include<unistd.h> 
#include<pthread.h>

void err_thread(int ret, char* str){
    fprintf(stderr, "%s error: %s\n", strerror(ret));
    exit(1);
}
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

struct msg{
    int val;
    struct msg *next;
};

msg *head = nullptr;

void* producer(void* arg){
    while(1){
        msg* mp = (msg*) malloc(sizeof(msg));
        mp -> val = rand() % 1000 + 1;
        printf("producer msg val is %d\n", mp ->val);
        pthread_mutex_lock(&mutex);
        mp->next = head;
        head = mp;
        pthread_mutex_unlock(&mutex);
        pthread_cond_signal(&cond);
//      sleep(rand() % 2);
	sleep(2);
    }
} 

void* consumer(void* arg){
    while(1){
       pthread_mutex_lock(&mutex);
       while(!head){
        pthread_cond_wait(&cond, &mutex);
       }
       printf("consumer msg val is %d\n", head -> val);
       msg* t = head;
       head = head -> next;
       pthread_mutex_unlock(&mutex);
       free(t); 
    }

}

int main(int argc, char* args[])
{
    int ret;
    pthread_t ptid, ctid;
    ret = pthread_create(&ptid, NULL, producer, NULL);
    if(ret){
        err_thread(ret, "pthread_create ptid");
    }

    ret = pthread_create(&ctid, NULL, consumer, NULL);
    if(ret){
        err_thread(ret, "pthread_create ctid");
    }

    pthread_join(ptid, NULL);
    pthread_join(ctid, NULL);
    
    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);

    return 0;
}
